package com.huahua.utils.util;

import com.huahua.utils.entity.PropertyInfo;
import com.huahua.utils.entity.PropertyInfo;
import com.huahua.utils.entity.TableInfo;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

@SuppressWarnings("all")
public class JDBCUtil {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;

    /*使用静态代码块获得dbconfig配置属性*/
    static {
        Properties properties = new Properties();
        String dbConfigPath = JDBCUtil.class.getClassLoader().getResource("dbConfig.properties").getPath();//获得在JDBCUtil类所在src下的指定文件dbConfig.properties的路径
        try {
            properties.load(new FileReader(dbConfigPath));//通过dbConfigPath路径读取properties对象，获得配置文件dbConfig里的文件属性
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*获取连接并
     *得到一个Connection
     *
     * */
    public static Connection getConnection() {
        Connection coun = null;
        try {
            //注册驱动
            Class.forName(driver);
            //建立数据库连接
            coun = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return coun;
    }


    /*
     * 释放资源
     * */
    public static void close(Connection connection, Statement statement) {
        statementClose(statement);
        connectionClose(connection);
    }

    public static void close(Connection connection, ResultSet resultSet) {
        resultSetClose(resultSet);
        connectionClose(connection);
    }

    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        resultSetClose(resultSet);
        statementClose(statement);
        connectionClose(connection);
    }

    /*
     * 释放数据库连接
     * */
    private static void connectionClose(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * 释放statement对象
     * */
    private static void statementClose(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * 释放返回结果对象
     * */
    private static void resultSetClose(ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    private static List<TableInfo> getTablesList() {
        List<TableInfo> tables = new ArrayList<>();
        Connection conn = getConnection();
        ResultSet rs = null;
        try {

            DatabaseMetaData dbmd = conn.getMetaData();
            String[] types = {"TABLE"};
            rs = dbmd.getTables(null, null, "%", types);
            while (rs.next()) {
                TableInfo tableInfo = new TableInfo();
                String tableName = rs.getString("TABLE_NAME");  //表名
                tableInfo.setTableName(tableName);
                tables.add(tableInfo);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, rs);
        }

        return tables;
    }

    private static final String SQL = "SELECT * FROM ";

    private static List<PropertyInfo> getPropertyList(String tableName) throws Exception {
        ArrayList<PropertyInfo> propertyInfos = new ArrayList<>();
        Connection connection = getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(SQL + tableName);
        ResultSetMetaData metaData = preparedStatement.getMetaData();
        int columnCount = metaData.getColumnCount();
        for (int i = 0; i < columnCount; i++) {
            String fieldName = metaData.getColumnName(i + 1);
            String fieldType = metaData.getColumnClassName(i + 1);
            PropertyInfo propertyInfo = fieldToProperty(fieldName, fieldType);
            propertyInfos.add(propertyInfo);
        }
        return propertyInfos;
    }


    public static PropertyInfo fieldToProperty(String fieldName,String fieldType) throws ClassNotFoundException {
        PropertyInfo propertyInfo = new PropertyInfo();

        propertyInfo.setName(getJavaName(fieldName));

        propertyInfo.setSimpleType(getJavaSimpleType(fieldType));

        return propertyInfo;
    }

    public static String getJavaName(String fieldName){
        if (null == fieldName) {
            throw new RuntimeException("字段名不能为空");
        }
        char[] chars = fieldName.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (c == '_') {
                int j = i + 1;
                if (j < chars.length) {
                    sb.append(StringUtils.upperCase(CharUtils.toString(chars[j])));
                    i++;
                }
            } else {
                sb.append(c);
            }
        }
        return  sb.toString();
    }

    private static String getJavaSimpleType(String fieldType) throws ClassNotFoundException {
        String javaType;
        if (fieldType==null){
            throw new RuntimeException("字段类型不能为空");
        }
        switch (fieldType) {
            case "java.sql.Timestamp":
                javaType=(Date.class.getName());
                break;
            case "java.sql.Date":
                javaType=(Date.class.getName());
                break;
            case "java.math.BigDecimal":
                javaType=(String.class.getSimpleName());
                break;
            default:
                javaType=Class.forName(fieldType).getSimpleName();
        }
        return javaType;
    }




    public static List<TableInfo> getTableDetails() throws Exception {
        PropertyInfo propertyInfo = new PropertyInfo();
        List<TableInfo> tablesList = getTablesList();
        for (TableInfo tableInfo : tablesList) {
            List<PropertyInfo> propertyList = getPropertyList(tableInfo.getTableName());
            tableInfo.setProperties(propertyList);
        }
        return tablesList;
    }

    public static void main(String[] args) throws Exception {
        List<TableInfo> tableDetails = getTableDetails();
        System.out.println();
    }

}
